﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace INSTA.BankApplication.Engine
{
    /// <summary>
    /// Abstract base class for all account types.
    /// </summary>
    public abstract class AccountBase
    {
        private IBankCustomer    _holder;
        private double      _balance;


        /// <summary>
        /// Occurs when some money is transferred from / to the account.
        /// </summary>
        public event EventHandler<MoneyTransferEventArgs> MoneyTransferred;
        

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="holder">The <see cref="IBankCustomer"/> that owns the account</param>
        /// <param name="initialDeposit">the amount to deposit on the account.</param>
        public AccountBase(IBankCustomer holder, double initialDeposit)
        {
            _holder = holder;

            Deposit(initialDeposit);
        }

        /**********************************************************************
         * 
         *  Properties
         *  
         **********************************************************************/


        /// <summary>
        /// The <see cref="IBankCustomer"/> that owns the account.
        /// </summary>
        public IBankCustomer Holder
        {
            get { return _holder; }

        }

        /// <summary>
        /// Gets the account's current Balance.
        /// </summary>
        public double Balance
        {
            get { return _balance; }
        }

        /// <summary>
        /// Returns true if the account exceeds its overdrawn limit, else false.
        /// </summary>
        public bool IsAccountExcessOverdrawn
        {
            get
            {
                bool result = _balance < -GetMaxOverdrawn();

                return result;
            }
        }


        /**********************************************************************
         * 
         *  Methods
         *  
         **********************************************************************/

        /// <summary>
        /// Executes the strategy.
        /// </summary>
        /// <param name="strategy">The strategy.</param>
        public void ExecuteStrategy(AccountStrategy strategy)
        {
            // Executes the specified strategy on the current instance.
            strategy.Run(this);
        }





        /// <summary>
        /// Deposits the specified amount on the account.
        /// </summary>
        /// <param name="amount">the amount to deposit (allways positive).</param>
        public void Deposit(double amount)
        {
            if (amount > 0)
            {
                _balance += amount;

                // Let's call the method that raises the event.
                OnMoneyTransferred(TransferType.Deposit, amount);
            }
        }

        /// <summary>
        /// Withdraws the specified amount from the account.
        /// </summary>
        /// <param name="amount">the amount to withdraw (allways positive).</param>
        public void Withdraw(double amount)
        {
            if (amount > 0)
            {
                _balance -= amount;

                // Let's call the method that raises the event.
                OnMoneyTransferred(TransferType.Withdraw, amount);
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="transferType">Type of the transfer.</param>
        /// <param name="amount">The amount.</param>
        protected virtual void OnMoneyTransferred(TransferType transferType, double amount)
        {
            MoneyTransferEventArgs e = new MoneyTransferEventArgs(transferType, amount, _balance);

            if (MoneyTransferred != null)
            {
                MoneyTransferred(this, e);
            }
        }





        /// <summary>
        /// Withdraws the monthly Fees from the Account.
        /// </summary>
        public abstract void WithdrawMonthlyFees();

        //// <summary>
        /// Gets the maximum authorized overdrawn (découvert) amount.
        /// </summary>
        /// <returns>the maximum authorized overdrawn (découvert) amount.</returns>
        public abstract double GetMaxOverdrawn();



       


    }
}
